package com.sike.netty.im.server.handler;

import cn.hutool.core.util.StrUtil;
import com.sike.netty.im.common.command.LoginRequestCommand;
import com.sike.netty.im.common.command.LoginResponseCommand;
import com.sike.netty.im.common.command.Message;
import com.sike.netty.im.common.command.MessageBuilder;
import com.sike.netty.im.common.enums.Attributes;
import com.sike.netty.im.common.enums.CommandTypeEnum;
import com.sike.netty.im.common.enums.ResponseStatusEnum;
import com.sike.netty.im.server.service.BeanFactory;
import com.sike.netty.im.server.service.SessionService;
import com.sike.netty.im.server.service.UserInfoCache;
import com.sike.netty.im.server.service.UserInfoDTO;
import com.sike.netty.im.server.util.LoginUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.AttributeKey;
import lombok.extern.slf4j.Slf4j;


/**
 * 登录 handler
 *
 * @author chenssy
 * @date 2023/09/14
 */
@Slf4j
public class LoginHandler extends SimpleChannelInboundHandler<LoginRequestCommand> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, LoginRequestCommand msg) throws Exception {
        if (StrUtil.isBlank(msg.getUsername()) || StrUtil.isBlank(msg.getPassword())) {
            throw new RuntimeException("登录失败，原因：用户名和密码不能为空");
        }

        UserInfoDTO userInfoDTO = UserInfoCache.getUserInfoByUserName(msg.getUsername());
        if (userInfoDTO == null || !msg.getPassword().equals(userInfoDTO.getPassword())) {
            throw new RuntimeException("登录失败，原因：用户名或密码错误");
        }

        // 用户名密码正常将 userid 与 Channel 绑定起来
        SessionService sessionService = (SessionService) BeanFactory.getServiceBean(SessionService.class);
        sessionService.bind(userInfoDTO.getUserId(), ctx.channel());

        // 标注 Channel 为已登录
        LoginUtil.markAsLogin(ctx.channel());
        // 设置该 Channel 的绑定用户
        LoginUtil.saveLoginUser(ctx.channel(),userInfoDTO.getUserId());

        LoginResponseCommand loginResponseCommand = new LoginResponseCommand();
        loginResponseCommand.setRetCode(ResponseStatusEnum.SUCCESS.getCode());
        loginResponseCommand.setRetMessage("登录成功");

        Message message = MessageBuilder.buildMessage(loginResponseCommand,null,null);
        ctx.channel().writeAndFlush(message);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.attr(AttributeKey.valueOf(Attributes.SERVER_EXCEPTION_RESPONSE_CLASS.getKey()))
                .set(CommandTypeEnum.LOGIN_RESPONSE_COMMAND.getCommandTypeClass());

        ctx.pipeline().get(ServerExceptionHandler.class).exceptionCaught(ctx,cause);
    }
}
